package flown.game.mine;



import java.util.ArrayList;
import java.util.HashMap;
import java.util.Objects;


/**
 * @author flown
 */

public class Block
{
    public enum Type
    {
        CONSTRUCTION,   ///< 建筑
        NATURE,         ///< 自然
        EQUIPMENT,      ///< 装备
        ITEM,           ///< 物品
        NONE            ///< 无分类
    }


    public static class Group
    {
        public static final String TEXT = "group";

        public static final Block.Group CONSTRUCTION = new Block.Group("construction");
        public static final Block.Group NATURE = new Block.Group("nature");
        public static final Block.Group EQUIPMENT = new Block.Group("equipment");
        public static final Block.Group ITEM = new Block.Group("item");
        public static final Block.Group NONE = new Block.Group("none");

        private String name = "none";
        private Block.Group prev_group = this;
        private HashMap<String,Block.Group> group = new HashMap<String,Block.Group>();///< 组,Block.Group.EQUIPMENT.group.get("farm").block_id.get(0);
        private ArrayList<Integer> block_id = new ArrayList<Integer>();

        // Block.Group.EQUIPMENT.group.get("weapon").group.get("gun").block_id.get(0);

        public Group() {}
        public Group(String name) { this.name = name; }
        public Group(String name, Block.Group prev_group) { this.name = name;this.prev_group = prev_group; }
        public final String GetName() { return this.name; }

        /**
         * @param group_name "group.equipment.weapon.gun" "equipment.weapon.gun"
         * @return Block.Group
         */
        public static Block.Group GetGroup(String group_name)
        {
            int count = 0;
            String[] name = group_name.split("\\.");
            Block.Group g = null;
            if (Objects.equals(name[count], Block.Group.TEXT))
                count++;

            int sort = 0;
            if (Objects.equals(name[count],Block.Group.CONSTRUCTION.GetName()))
                sort = 1;
            else if (Objects.equals(name[count],Block.Group.NATURE.GetName()))
                sort = 2;
            else if (Objects.equals(name[count],Block.Group.EQUIPMENT.GetName()))
                sort = 3;
            else if (Objects.equals(name[count],Block.Group.ITEM.GetName()))
                sort = 4;
            else if (Objects.equals(name[count],Block.Group.NONE.GetName()))
                sort = 5;

            g = switch(sort) {
                case 1 -> Block.Group.CONSTRUCTION;
                case 2 -> Block.Group.NATURE;
                case 3-> Block.Group.EQUIPMENT;
                case 4 -> Block.Group.ITEM;
                case 5 -> Block.Group.NONE;
                default -> null;
            };


            if (g != null)
            {
                count++;
                while(count < name.length)
                {
                    if (g.group.get(name[count]) == null)
                        g.group.put(name[count],new Block.Group(name[count], g));
                    g = g.group.get(name[count]);
                    count++;
                }
            }

            return g;
        }

        public static String GetGroupStr(Block.Group g)
        {
            Block.Group prev_group = g;
            ArrayList<String> group_name = new ArrayList<String>();
            while (prev_group.prev_group != prev_group)
            {
                group_name.add(prev_group.name);
                prev_group = g.prev_group;
            }

            StringBuilder str = new StringBuilder(prev_group.name);
            for (int i = group_name.size() - 1;i >= 0;i--)
            {
                str.append("\\." + group_name.get(i));
            }

            return str.toString();
        }

        public static Block.Group GetFirstGroup(Block.Group g)
        {
            Block.Group first_group = g;
            while (first_group.prev_group != first_group)
                first_group = first_group.prev_group;
            return first_group;
        }


        /**
         * Block.Group.AddGroup(Block.Group.ITEM, "farm");
         * @param g 要添加组的组
         * @param name 组名
         */
        public static void AddGroup(Block.Group g, String name) {Block.Group.AddGroup(g, new Block.Group(name));}

        /**
         * Block.Group.AddGroup(Block.Group.ITEM, "farm", farm_group);
         * @param g 要添加组的组
         * @param ag 要添加的组
         */
        public static void AddGroup(Block.Group g, Block.Group ag)
        {
            g.group.put(ag.GetName(),ag);
        }



        public final Block.Group GetPrevGroup() { return this.prev_group; }
        public final Block.Group GetNextGroup(String text)
        {
            String[] group_name = text.split("\\.");

            Block.Group g = this;
            for (int count = 0;count < group_name.length;count++)
            {
                String group_text = Block.Group.GetGroupStr(g) + "\\." + group_name[count];
                g = Block.Group.GetGroup(group_text);
            }

            return g;
        }

    }


    private static final HashMap<Integer, Block> id_block_map = new HashMap<Integer, Block>();

    private int id;
    private String name = "name";
    private Block.Type type = Block.Type.NONE;
    private Block.Group group;

    public boolean register_to_create_menu = true;     ///< 是否注册到创造栏
    public boolean solid = true;                       ///< 方块是否为实心方块,主要与生物在方块内时是否受到窒息伤害有关。true为实心。
    public boolean breath_ability = false;             ///< 方块的透气性，作为固体或是空气
    public boolean movable = true;                     ///< 方块能否被活塞推动,true则能拉
    public boolean only_piston_push = true;            ///< 方块是否会跟随粘性活塞移动
    public boolean break_on_push = false;              ///< 方块是否可以被活塞破坏变成掉落物
    public boolean jumping = true;                     ///< 踩在方块上时是否可以跳跃,prevents 防止
    public boolean walkable = true;                    ///< 踩在方块上时是否可以行走
    public boolean pathable = false;                   ///< 游戏内AI在进行寻路时，方块是否被当作障碍物。为true时，寻路时被当作空气

    public float destroy_time = 1;                         ///< 挖掘所需的时间
    public float block_light_emission = 0;                 ///< 方块亮度
    public float explosion_resistance = 0;                 ///< 爆炸抗性
    public java.awt.Color map_color = java.awt.Color.RED;  ///< 方块显示在地图上的颜色

    private ArrayList<Block.Group> block_filter = null; ///< 方块在什么方块上可以放置,为null时都能放
    private final ArrayList<flown.game.mine.component.Component> component = new ArrayList<flown.game.mine.component.Component>();

    /**
     * @param id block id
     * @param name block name
     * @param group_name "Group.EQUIPMENT.weapon" "Group.EQUIPMENT.weapon.gun" "EQUIPMENT.weapon"
     */
    public Block(int id, String name, String group_name)
    {
        this.id = id;
        this.name = name;

        Block block = Block.id_block_map.get(this.id);
        if (block != null)
        {
            block.group.block_id.remove(this.id);
        }

        this.group = Block.Group.GetGroup(group_name);
        if (this.group == null)
            this.group = Block.Group.NONE;
        this.group.block_id.add(this.id);


        String g_first_name = Block.Group.GetFirstGroup(this.group).GetName();
        if (Objects.equals(g_first_name, Group.CONSTRUCTION.GetName()))
            this.type = Block.Type.CONSTRUCTION;
        else if (Objects.equals(g_first_name, Group.NATURE.GetName()))
            this.type = Block.Type.NATURE;
        else if (Objects.equals(g_first_name, Group.EQUIPMENT.GetName()))
            this.type = Block.Type.EQUIPMENT;
        else if (Objects.equals(g_first_name, Group.ITEM.GetName()))
            this.type = Block.Type.ITEM;


        Block.id_block_map.put(this.id,this);
    }

    public static Block GetBlock(int id)
    {
        return Block.id_block_map.get(id);
    }


    public final void DisplayName()
    {

    }

}


